package jcu.sal.common;

import java.io.Serializable;

import jcu.sal.common.exceptions.SensorControlException;

/**
 * Objects of this class encapsulate the result of the execution of a command on a sensor.
 * The result can be retrieved using one of the <code>get*</code> methods. If a response object is part of
 * a data stream, usually obtained from a callback method, the <code>get*</code> methods may raise a
 * <code>SensorControlException</code>, thrown by the agent to indicate an error of some sort (stream terminated,
 * error getting reading, ...). The <code>getCause()</code> method invoked on the exception will show the
 * source of the error.
 * @author gilles
 *
 */
public class Response implements Serializable {
	private static final long serialVersionUID = -4090794353146528167L;
	private byte[] b;
	private String sid;
	private SensorControlException exception;
	private long timeStamp;
	
	public Response(byte[] bb, String sid) {
		timeStamp = System.currentTimeMillis();
		this.sid = sid;
		exception = null;
		if(bb==null)
			b= new byte[0];
		else
			b = bb;
	}
	
	/**
	 * This constructor builds a response object with either the errror or the end flag set. It is only intended to be used
	 * by streaming threads returning a response via a callback method 
	 * @param sid the sensor id
	 * @param e whether there was an error or not (normal end of stream)
	 */
	public Response(String sid, SensorControlException e){
		this(null,sid);
		b=null;
		exception = e;
	}
	
	/**
	 * This method returns the sensor identifier of the sensor which generated the response
	 * @return the sensor identifier of the sensor which generated the response
	 */
	public String getSID() {
		return sid;
	}
	
	/**
	 * This method returns the raw data from the sensor as a byte array.
	 * @return the raw data from the sensor 
	 * @throws SensorControlException if there was an error getting the raw data at the sensor
	 */
	public byte[] getBytes() throws SensorControlException {
		if(b==null && exception!=null)
			throw exception;
		return b;
	}
	
	/**
	 * This method returns the length of the raw data from the sensor.
	 * @return the raw data from the sensor 
	 * @throws SensorControlException if there was an error getting the raw data at the sensor
	 */
	public int getLength() throws SensorControlException{
		return getBytes().length;
	}
	
	/**
	 * This method returns the raw data from the sensor as a string
	 * @return the raw data from the sensor as a string
	 * @throws SensorControlException if there was an error getting the raw data at the sensor
	 */
	public String getString() throws SensorControlException {
		return new String(getBytes());
	}
	
	/**
	 * This method returns the raw data from the sensor as an integer
	 * @return the raw data from the sensor as an integer
	 * @throws SensorControlException if there was an error getting the raw data at the sensor
	 */
	public int getInt() throws SensorControlException {
		return Integer.parseInt(getString());
	}
	
	/**
	 * This method returns the raw data from the sensor as a float.
	 * @return the raw data from the sensor as a float.
	 * @throws SensorControlException if there was an error getting the raw data at the sensor
	 */
	public float getFloat() throws SensorControlException {
		return Float.parseFloat(getString());
	}
	
	/**
	 * This method returns a timestamp (generated by the SAL agent) at which the reading was generated.  
	 * @return a UNIX timestamp (number of milliseconds elapsed since 1 Jan 1970)
	 */
	public long getTimeStamp(){
		return timeStamp;
	}
}
